package assembler;

public class Code {
	private String op;
	private int state = 0;
	private int rd = 0, rs = 0, rt = 0;
	private int shift = 0;
	private int offset = 0;
	private int address = 0;
	private String codeline;

	Code(String codeline) {
		this.codeline = codeline;
	}

	/*
	 * String setcode1(String str) work for add/sub/mul/or/xor/
	 */
	private String setcode1(String str) {
		String sub = "";
		int i = 0, j = 0;
		op = str;
		state = 1;
		j = codeline.indexOf(" ");
		i = codeline.indexOf('r', j);
		j = codeline.indexOf(",", i);
		sub = codeline.substring(i + 1, j);
		rd = Integer.valueOf(sub);

		i = codeline.indexOf('r', j);
		j = codeline.indexOf(",", i);
		sub = codeline.substring(i + 1, j);
		System.out.println(sub);
		rs = Integer.valueOf(sub);

		rt = Integer.valueOf(codeline.substring(codeline.indexOf('r', j) + 1));
		System.out
				.println("op:" + op + ";rd:" + rd + ";rs:" + rs + ";rt:" + rt);
		return getcode(shift, rd, rs, rt);
	}

	/*
	 * String setcode2(String str) 
	 * 
	 * work for sra/srl/sll
	 */
	private String setcode2(String str) {

		String sub = "";
		int i = 0, j = 0;
		op = str;
		j = codeline.indexOf(" ");
		i = codeline.indexOf('r', j);
		j = codeline.indexOf(",", i);
		sub = codeline.substring(i + 1, j);
		rd = Integer.valueOf(sub);

		i = codeline.indexOf('r', j);
		j = codeline.indexOf(",", i);
		sub = codeline.substring(i + 1, j);
		rt = Integer.valueOf(sub);

		shift = Integer.valueOf(codeline.substring(j + 1));
		return getcode(shift, rd, rs, rt);
	}

	/*
	 * String setcode3(String str) work for jreg
	 */
	private String setcode3(String str) {
		String sub = "";
		int i = 0, j = 0;
		op = str;
		j = codeline.indexOf(" ");
		i = codeline.indexOf('r', j);
		sub = codeline.substring(i + 1);
		rs = Integer.valueOf(sub);
		return getcode(0, 0, rs, 0);
	}

	/*
	 * String setcode4(String str) work for addi/muli/andi/ori/xori
	 */
	private String setcode4(String str) {
		String sub = "";
		int i = 0, j = 0;
		op = str;
		j = codeline.indexOf(" ");
		i = codeline.indexOf('r', j);
		j = codeline.indexOf(",", i);
		sub = codeline.substring(i + 1, j);
		rt = Integer.valueOf(sub);

		i = codeline.indexOf('r', j);
		j = codeline.indexOf(",", i);
		sub = codeline.substring(i + 1, j);
		rs = Integer.valueOf(sub);

		shift = Integer.valueOf(codeline.substring(j + 1));
		System.out
		.println("op:" + op + ";rd:" + rd + ";rs:" + rs + ";rt:" + rt+";shift"+shift);
		return getcode(shift, rs, rt);
	}
	/*
	 * String setcode5(String str)
	 * work for load/store/beq/bne 
	 */
	private String setcode5(String str){
		String sub="";
		int i=0,j=0;
		op=str;
		j=codeline.indexOf(" ");
		i=codeline.indexOf("r",j);
		j=codeline.indexOf(",",i);
		sub=codeline.substring(i+1,j);
		rt=Integer.valueOf(sub);
		
		i=j+1;
		j=codeline.indexOf("(",i);
		sub=codeline.substring(i,j);
		offset=Integer.valueOf(sub);
		
		i=j+2;
		j=codeline.indexOf(")");
		sub=codeline.substring(i,j);
		rs=Integer.valueOf(sub);
		
		return getcode(offset,rs,rt);
	}
	
	/*
	 * String setcode6(String str)
	 * work for lui
	 */
	private String setcode6(String str){
		String sub="";
		int i=0,j=0;
		op=str;
		j=codeline.indexOf(" ");
		i=codeline.indexOf("r",j);
		j=codeline.indexOf(",",i);
		sub=codeline.substring(i+1,j);
		rt=Integer.valueOf(sub);
		
		i=j+1;
		sub=codeline.substring(i);
		shift=Integer.valueOf(sub);
		return getcode(shift,rs,rt);
	}
	/*
	 * String setcode7(String str)
	 * work for jump/jal 
	 */
	private String setcode7(String str){
		String sub="";
		int i=0;
		op=str;
		i=codeline.indexOf(" ");
		sub=codeline.substring(i+1);
		address=Integer.valueOf(sub);
		return getcode(address);
	}
	private String getn(int n, int t) {
		String ans = "";
		String str;
		str = Integer.toString(t, 2);
		for (int i = n; i > str.length(); i--) {
			ans += '0';
		}
		ans += str;
		return ans;
	}
	private String getn(int n,String str){
		String ans = "";
		for (int i = n; i > str.length(); i--) {
			ans += '0';
		}
		ans += str;
		return ans;
	}
	private String getcode(int n1, int n2, int n3, int n4) {
		String str = "";
		str = OP.get(op) + getn(5, n1) + getn(5, n2) + getn(5, n3)
				+ getn(5, n4);
		return str;
	}

	private String getcode(int n1, int n2, int n3) {
		String str = "";
		str = OP.get(op) + getn(16, n1) + getn(5, n2) + getn(5, n3);
		return str;
	}

	private String getcode(int n1) {
		String str = "";
		str = OP.get(op) + getn(26, n1);
		return str;
	}

	public String toString(int n) {
		int i = 0, j = 0;
		String str = "";
		String ans = "";
		str = codeline.substring(0, codeline.indexOf(" "));
		System.out.println(str);
		switch (str) {
		case "add":
			ans = setcode1(str);
			break;
		case "sub":
			ans = setcode1(str);
			break;
		case "mul":
			ans = setcode1(str);
			break;
		case "and":
			ans = setcode1(str);
			break;
		case "or":
			ans = setcode1(str);
			break;
		case "xor":
			ans = setcode1(str);
			break;
		case "sra":
			ans = setcode2(str);
			break;
		case "srl":
			ans = setcode2(str);
			break;
		case "sll":
			ans = setcode2(str);
			break;
		case "jreg":
			ans = setcode3(str);
			break;
		case "addi":
			ans=setcode4(str);
			break;
		case "muli":
			ans=setcode4(str);
			break;
		case "andi":
			ans=setcode4(str);
			break;
		case "ori":
			ans=setcode4(str);
			break;
		case "xori":
			ans=setcode4(str);
			break;
		case "load":
			ans=setcode5(str);
			break;
		case "store":
			ans=setcode5(str);
			break;
		case "beq":
			ans=setcode5(str);
			break;
		case "bne":
			ans=setcode5(str);
			break;
		case "lui":
			ans=setcode6(str);
			break;
		case "jump":
			ans=setcode7(str);
			break;
		case "jal":
			ans=setcode7(str);
			break;
		default:
			System.out.println("err:Line"+n);
			break;
		}
		int t;
		t=Integer.parseInt(ans, 2);
		ans=Integer.toString(t,16);
		ans=getn(8,ans);
		
		ans='\t'+"assign rom[6'h"+getn(2,Integer.toString(n, 16))
				+"]=32'h"+ans+";//"+codeline;
		return ans;
	}

	public static void main(String[] args) {
		Code code = new Code("addi r5,r0,4");
		System.out.println(code.toString(11));
	}
}
